﻿//-------------------------------------
// WBFSSync - WBFSSync.exe
//
// Copyright 2009 Caian (ÔmΣga Frøst) <frost.omega@hotmail.com> :
//
// WBFSSync is Licensed under the terms of the Microsoft Reciprocal License (Ms-RL)
//
// UpdateCreator.cs:
//
// Classe que controla a criação de pacotes de atualização
//
// Formato do arquivo UPDATE.inf
//
// VERSION: X.X.XX
// COREFILE: PATH|SIZE|VERSION|MD5 HASH - 128BIT
// ...
// LANGUAGE: PATH|SIZE
// ...
// SKIN: PATH|NUM FILES
// SKIN FILE PATH|SIZE
// ...
// ...
//
//-------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;

namespace DevConsole
{
    static class UpdateCreator
    {
        //-------------------------------
        const String ProjectPath = "..\\..\\..\\";
        const String ReleasePath = "Releases\\";
        const String UpdatePath = "UPDATE\\";

        const String LanguagePath = "Language\\";
        const String SkinPath = "Skin\\";
        const String DefaultSkin = "AeroSeven";
        
        const String ChangelogFile = "changelog.txt";
        const String LicenseFile = "license.txt";
        const String UpdateInfFile = "UPDATE.inf";

        //-------------------------------
        internal static List<String> CoreFiles = new List<string>();
        internal static List<String> LanguageFiles = new List<string>();
        internal static List<String> SkinFiles = new List<string>();
        internal static String[] Changelog = new string[0];
        internal static String Version = "";

        //-------------------------------
        public static void UpdateCommand(String[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("makerelease VERSION");
                return;
            }

            CoreFiles.Clear();
            LanguageFiles.Clear();
            SkinFiles.Clear();
            Changelog = new string[0];
            Version = "";

            //Módulos
            if(File.Exists("modules.txt"))
            {
                String[] modules = File.ReadAllLines("modules.txt");
                foreach (string module in modules)
                {
                    if (module.Length == 0) continue;
                    CoreFiles.Add(Path.GetFullPath(ProjectPath + module));
                }
            }

            //Idiomas
            String[] languages = Directory.GetFiles(ProjectPath + LanguagePath, "*.inf");
            LanguageFiles.AddRange(languages);

            //Skins
            String[] skins = Directory.GetDirectories(ProjectPath + SkinPath);
            foreach (string skin in skins)
            {
                string dirname = Path.GetFileName(skin);
                if (dirname.StartsWith("_")) continue;
                SkinFiles.Add(skin);
            }

            //Changelog
            if (File.Exists(ProjectPath + ChangelogFile))
            {
                Changelog = File.ReadAllLines(ProjectPath + ChangelogFile, Encoding.Default);
            }

            //

            Console.WriteLine("Loading GUI...");

            FormUpdateCreator form = new FormUpdateCreator();
            form.textBox_version.Text = args[1];
            form.richTextBox_changelog.Lines = Changelog;

            foreach (string corefile in CoreFiles)
                form.checkedListBox_corefiles.Items.Add(Path.GetFileNameWithoutExtension(corefile), true);

            foreach (string langfile in LanguageFiles) 
                form.checkedListBox_languagefiles.Items.Add(Path.GetFileNameWithoutExtension(langfile), true);

            foreach (string skinfile in SkinFiles) 
                form.checkedListBox_skinfiles.Items.Add(Path.GetFileNameWithoutExtension(skinfile), true);

            if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {

                //

                Changelog = form.richTextBox_changelog.Lines;
                Version = form.textBox_version.Text;

                for (int i = form.checkedListBox_corefiles.Items.Count - 1; i >= 0; i--)
                {
                    if (!form.checkedListBox_corefiles.GetItemChecked(i))
                        CoreFiles.RemoveAt(i);
                }

                for (int i = form.checkedListBox_languagefiles.Items.Count - 1; i >= 0; i--)
                {
                    if (!form.checkedListBox_languagefiles.GetItemChecked(i))
                        LanguageFiles.RemoveAt(i);
                }

                for (int i = form.checkedListBox_skinfiles.Items.Count - 1; i >= 0; i--)
                {
                    if (!form.checkedListBox_skinfiles.GetItemChecked(i))
                        SkinFiles.RemoveAt(i);
                }

                //

                CreateRelease();
            }

            //
            Console.WriteLine("Done\n");
        }

        //-------------------------------
        private static void CreateRelease()
        {
            Stream updatefile = File.Open(ProjectPath + UpdatePath + UpdateInfFile, FileMode.Create, FileAccess.Write,
                FileShare.Read);
            StreamWriter writer = new StreamWriter(updatefile, Encoding.Default);
            writer.WriteLine("VERSION:{0}", Version);

            String updatedir = ProjectPath + UpdatePath + Version + '\\';
            String updatedirsrv = UpdatePath + Version + '\\';

            String releasedir = ProjectPath + ReleasePath + Version + '\\';

            Directory.CreateDirectory(updatedir);

            Directory.CreateDirectory(releasedir);
            Directory.CreateDirectory(releasedir + LanguagePath);
            Directory.CreateDirectory(releasedir + SkinPath);

            //Módulos

            foreach (String module in CoreFiles)
            {
                string version = "";
                string md5hash = "";
                long filesize = 0;

                FileInfo fi = new FileInfo(module);
                filesize = fi.Length;

                fi = null;

                Assembly assembly = Assembly.LoadFile(module);
                version = assembly.GetName().Version.ToString();
                assembly = null;

                FileStream f = File.OpenRead(module);
                MD5 md5 = MD5.Create();
                byte[] bhash = md5.ComputeHash(f);
                for (int i = 0; i < bhash.Length; i++) md5hash += bhash[i].ToString("X");

                md5 = null;
                f.Close();
                f = null;
                bhash = null;

                File.Copy(module, updatedir + Path.GetFileName(module), true);
                File.Copy(module, releasedir + Path.GetFileName(module), true);
                
                //-----------------

                writer.WriteLine("COREFILE:{0}{1}|{2}|{3}|{4}", updatedirsrv, Path.GetFileName(module), filesize, version,
                    md5hash);
            }

            //Idiomas
            foreach (String language in LanguageFiles)
            {
                //Sem hashing nesses arquivos...
                long filesize = 0;

                FileInfo fi = new FileInfo(language);
                filesize = fi.Length;

                fi = null;

                writer.WriteLine("LANGUAGE:{0}{1}|{2}", LanguagePath, Path.GetFileName(language), filesize);
                File.Copy(language, releasedir + LanguagePath + Path.GetFileName(language), true);
            }

            //Skin
            foreach (String skin in SkinFiles)
            {
                String[] files = Directory.GetFiles(skin);
                writer.WriteLine("SKIN:{0}{1}|{2}", SkinPath, Path.GetFileNameWithoutExtension(skin), files.Length);

                DirectoryInfo di = Directory.CreateDirectory(releasedir + SkinPath + Path.GetFileNameWithoutExtension(skin));

                foreach (String file in files)
                {
                    //Sem hashing nesses arquivos...
                    long filesize = 0;

                    FileInfo fi = new FileInfo(file);
                    filesize = fi.Length;

                    fi = null;

                    writer.WriteLine(":{0}|{1}", Path.GetFileName(file), filesize);
                    File.Copy(file, di.FullName + '\\' + Path.GetFileName(file), true);
                }
            }

            //Changelog

            File.WriteAllLines(ProjectPath + ChangelogFile, Changelog, Encoding.Default);
            File.Copy(ProjectPath + ChangelogFile, releasedir + ChangelogFile, true);

            //Licença
            File.Copy(ProjectPath + LicenseFile, releasedir + LicenseFile, true);

            writer.Close();
            writer = null;
            updatefile = null;
        }
    }
}
